import { AxiosRequestConfig, AxiosResponseTransformer, HttpStatusCode } from 'axios'
import { SUCCESS_CODE } from '@/core/constants/coreConstants'
import serverApiUtils from '@/core/utils/serverApiUtils'
import lodash from 'lodash'
import { R } from '@/components/axios/interface'
import globalConfig from '@/core/framework/config/globalConfig'
import http from '@/components/axios/http'
import Oauth2ErrorResponse from '@/core/oauth2/types/model/response/Oauth2ErrorResponse'
import Oauth2IntrospectResponse from '@/core/oauth2/types/model/response/Oauth2IntrospectResponse'
import LoginByPasswordRequest from '@/core/oauth2/types/model/request/LoginByPasswordRequest'
import { TokenInfoResponse } from '@/core/oauth2/types/model/response/TokenInfoResponse'
import Oauth2RevokeResponse from '@/core/oauth2/types/model/response/Oauth2RevokeResponse'
import { Base64 } from 'js-base64'
import HttpHeaders from '@/core/http/constants/HttpHeaders'
import oauth2ApiConfig from '@/core/oauth2/apiconfig/oauth2ApiConfig'

const oauth2TransformResponse: AxiosResponseTransformer = (data, headers, status): R<void> => {
	if (status != HttpStatusCode.Ok) {
		return data
	}
	const resJson: any | Oauth2ErrorResponse = JSON.parse(data)

	if (resJson.hasOwnProperty('error')) {
		return {
			code: resJson.error,
			message: resJson.error_description,
		} as R<undefined>
	} else {
		return {
			code: SUCCESS_CODE,
			data: resJson,
		} as R<void>
	}
}

class Oauth2ServerApi {
	introspect = (token: string, authorization: string): Promise<R<Oauth2IntrospectResponse>> => {
		const config = lodash.merge(
			{
				data: { token: token },
				headers: { [globalConfig.authorizationKey]: authorization },
				transformResponse: oauth2TransformResponse,
			} as AxiosRequestConfig,
			serverApiUtils.convertApiConfig(oauth2ApiConfig.oauth2IntrospectApi),
		)

		return http.post(config)
	}

	introspectByClient = (token: string, clientId: string, clientSecret: string): Promise<R<Oauth2IntrospectResponse>> => {
		const authorization: string = Base64.encode(`${globalConfig.clientId}:${globalConfig.clientSecret}`)
		return this.introspect(token, authorization)
	}

	loginByPassword = async (data: LoginByPasswordRequest): Promise<R<TokenInfoResponse>> => {
		const config = lodash.merge(
			{
				data: data,
				transformResponse: oauth2TransformResponse,
			} as AxiosRequestConfig,
			serverApiUtils.convertApiConfig(oauth2ApiConfig.getTokenByPasswordGrantType),
		)
		return http.post(config)
	}

	logout = (accessToken: string): Promise<R<Oauth2RevokeResponse>> => {
		const config = lodash.merge(
			{
				headers: { [globalConfig.authorizationKey]: accessToken },
				transformResponse: oauth2TransformResponse,
			} as AxiosRequestConfig,
			serverApiUtils.convertApiConfig(oauth2ApiConfig.oauth2RevokeApi),
		)

		return http.post(config)
	}

	/**
	 * 客户端认证方式 获取token
	 * @param clientId
	 * @param clientSecret
	 */
	getTokenByClientGrantType = (clientId: string, clientSecret: string): Promise<R<TokenInfoResponse>> => {
		const authorization: string = Base64.encode(`${globalConfig.clientId}:${globalConfig.clientSecret}`)
		const config = lodash.merge(
			{
				headers: {
					[HttpHeaders.AUTHORIZATION]: 'Basic ' + authorization,
				},
				transformResponse: oauth2TransformResponse,
			} as AxiosRequestConfig,
			serverApiUtils.convertApiConfig(oauth2ApiConfig.getTokenByClientGrantType),
		)
		return http.post(config)
	}
}

const oauth2ServerApi = new Oauth2ServerApi()
export default oauth2ServerApi
